今天是第二十二天我們可以寫一個k8s選課資料庫管理系統,以下是我的程式碼
創建一個 mysql-deployment.yaml 檔案來部署 MySQL。
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: mysql-pv-claim
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 10Gi
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: mysql
spec:
selector:
matchLabels:
app: mysql
template:
metadata:
labels:
app: mysql
spec:
containers:
- name: mysql
image: mysql:5.7
env:
- name: MYSQL_ROOT_PASSWORD
value: "password"
- name: MYSQL_DATABASE
value: "course_db"
- name: MYSQL_USER
value: "admin"
- name: MYSQL_PASSWORD
value: "password"
ports:
- containerPort: 3306
volumeMounts:
- name: mysql-persistent-storage
mountPath: /var/lib/mysql
volumes:
- name: mysql-persistent-storage
persistentVolumeClaim:
claimName: mysql-pv-claim
---
apiVersion: v1
kind: Service
metadata:
name: mysql
spec:
ports:
- port: 3306
selector:
app: mysql
創建一個簡單的 Flask API,與 MySQL 互動。首先,撰寫 app.py:
from flask import Flask, request, jsonify
import mysql.connector
app = Flask(__name__)
def get_db_connection():
conn = mysql.connector.connect(
host='mysql', # Kubernetes 服務名稱
user='admin',
password='password',
database='course_db'
)
return conn
@app.route('/courses', methods=['GET'])
def get_courses():
conn = get_db_connection()
cursor = conn.cursor()
cursor.execute('SELECT * FROM courses')
courses = cursor.fetchall()
cursor.close()
conn.close()
return jsonify(courses)
@app.route('/enroll', methods=['POST'])
def enroll_course():
student_id = request.json['student_id']
course_id = request.json['course_id']
conn = get_db_connection()
cursor = conn.cursor()
cursor.execute('INSERT INTO enrollments (student_id, course_id) VALUES (%s, %s)', (student_id, course_id))
conn.commit()
cursor.close()
conn.close()
return 'Enrolled successfully!', 201
if __name__ == '__main__':
app.run(host='0.0.0.0', port=5000)
創建 Dockerfile 來打包 Flask API:
FROM python:3.8-slim
WORKDIR /app
COPY requirements.txt requirements.txt
RUN pip install -r requirements.txt
COPY . .
CMD ["python", "app.py"]
requirements.txt:
Flask
mysql-connector-python
接著,創建 flask-deployment.yaml:
apiVersion: apps/v1
kind: Deployment
metadata:
name: flask-api
spec:
selector:
matchLabels:
app: flask-api
template:
metadata:
labels:
app: flask-api
spec:
containers:
- name: flask-api
image: your-dockerhub-username/flask-api:latest
ports:
- containerPort: 5000
---
apiVersion: v1
kind: Service
metadata:
name: flask-api
spec:
ports:
- port: 5000
selector:
app: flask-api
創建一個簡單的 index.html:
<!DOCTYPE html>
<html>
<head>
<title>選課系統</title>
</head>
<body>
<h1>選課系統</h1>
<form id="enrollForm">
學生 ID: <input type="text" id="student_id"><br><br>
課程 ID: <input type="text" id="course_id"><br><br>
<button type="submit">選課</button>
</form>
<h2>已選課程</h2>
<ul id="coursesList"></ul>
<script>
document.getElementById('enrollForm').onsubmit = function(event) {
event.preventDefault();
const studentId = document.getElementById('student_id').value;
const courseId = document.getElementById('course_id').value;
fetch('/enroll', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ student_id: studentId, course_id: courseId })
})
.then(response => response.text())
.then(data => alert(data));
};
fetch('/courses')
.then(response => response.json())
.then(courses => {
const coursesList = document.getElementById('coursesList');
courses.forEach(course => {
const li = document.createElement('li');
li.textContent = `課程 ID: ${course[0]}, 課程名稱: ${course[1]}`;
coursesList.appendChild(li);
});
});
</script>
</body>
</html>
將此前端部署在 Nginx 上,並創建 nginx-deployment.yaml:
apiVersion: apps/v1
kind: Deployment
metadata:
name: frontend
spec:
selector:
matchLabels:
app: frontend
template:
metadata:
labels:
app: frontend
spec:
containers:
- name: nginx
image: nginx:latest
volumeMounts:
- name: html
mountPath: /usr/share/nginx/html
volumes:
- name: html
configMap:
name: frontend-html
---
apiVersion: v1
kind: ConfigMap
metadata:
name: frontend-html
data:
index.html: |
# (Paste index.html content here)
---
apiVersion: v1
kind: Service
metadata:
name: frontend
spec:
ports:
- port: 80
selector:
app: frontend
運行以下指令將部署所有服務:
kubectl apply -f mysql-deployment.yaml
kubectl apply -f flask-deployment.yaml
kubectl apply -f nginx-deployment.yaml
這樣,Kubernetes 就會運行選課系統,前端透過 Nginx 提供服務,後端 Flask API 處理選課請求,並與 MySQL 進行互動。
在 mysql-deployment.yaml 中,定義了 MySQL 資料庫的 Kubernetes 資源。這裡主要包含以下幾個部分:
這段程式碼是用來申請一塊持久性存儲空間,用於 MySQL 存儲資料。
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: mysql-pv-claim
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 10Gi
PersistentVolumeClaim (PVC):它用來請求一塊 10GB 的持久存儲。這塊存儲將會被用來保存 MySQL 資料庫的數據,即使 Pod 被重啟,數據也不會丟失。accessModes:設置為 ReadWriteOnce,表示這塊存儲可以被一個節點讀寫。MySQL 被打包成一個容器,這裡通過 Deployment 創建和管理 MySQL Pod。
apiVersion: apps/v1
kind: Deployment
metadata:
name: mysql
spec:
selector:
matchLabels:
app: mysql
template:
metadata:
labels:
app: mysql
spec:
containers:
- name: mysql
image: mysql:5.7
env:
- name: MYSQL_ROOT_PASSWORD
value: "password"
- name: MYSQL_DATABASE
value: "course_db"
- name: MYSQL_USER
value: "admin"
- name: MYSQL_PASSWORD
value: "password"
ports:
- containerPort: 3306
volumeMounts:
- name: mysql-persistent-storage
mountPath: /var/lib/mysql
volumes:
- name: mysql-persistent-storage
persistentVolumeClaim:
claimName: mysql-pv-claim
Deployment:定義了 MySQL 容器的部署,管理 MySQL 的 Pod。image: mysql:5.7:指定 MySQL 的 Docker 鏡像版本。env:環境變量,用來設定 MySQL 的 root 密碼、資料庫名稱以及用戶憑證。volumeMounts:將 PVC 持久化存儲掛載到容器內 /var/lib/mysql 目錄,這是 MySQL 存放數據的地方。apiVersion: v1
kind: Service
metadata:
name: mysql
spec:
ports:
- port: 3306
selector:
app: mysql
Service:定義了如何對外暴露 MySQL 服務,讓其他 Pod(如 Flask API)可以通過 Kubernetes 的內部 DNS 名稱(mysql)來訪問資料庫。port: 3306:指定 MySQL 使用的默認端口。Flask API 是一個簡單的應用,它用來與 MySQL 資料庫互動,處理選課相關的操作。
from flask import Flask, request, jsonify
import mysql.connector
app = Flask(__name__)
Flask:引入 Flask 框架來處理 HTTP 請求。mysql.connector:用來與 MySQL 資料庫連接。app = Flask(__name__):初始化 Flask 應用,並且可以設定各種路由。def get_db_connection():
conn = mysql.connector.connect(
host='mysql', # Kubernetes 服務名稱
user='admin',
password='password',
database='course_db'
)
return conn
get_db_connection():用來建立與 MySQL 資料庫的連接。host='mysql' 表示 MySQL 是通過 Kubernetes 的內部 DNS 名稱來訪問。user、password、database:與 MySQL 連接所需的憑證。@app.route('/courses', methods=['GET'])
def get_courses():
conn = get_db_connection()
cursor = conn.cursor()
cursor.execute('SELECT * FROM courses')
courses = cursor.fetchall()
cursor.close()
conn.close()
return jsonify(courses)
@app.route('/courses', methods=['GET']):定義了一個 GET 請求的 API,URL 是 /courses。這個 API 會查詢所有課程。cursor.execute('SELECT * FROM courses'):從 courses 資料表中查詢所有課程。jsonify(courses):將查詢結果轉換成 JSON 格式,回傳給客戶端。@app.route('/enroll', methods=['POST'])
def enroll_course():
student_id = request.json['student_id']
course_id = request.json['course_id']
conn = get_db_connection()
cursor = conn.cursor()
cursor.execute('INSERT INTO enrollments (student_id, course_id) VALUES (%s, %s)', (student_id, course_id))
conn.commit()
cursor.close()
conn.close()
return 'Enrolled successfully!', 201
@app.route('/enroll', methods=['POST']):定義了一個 POST 請求的 API,URL 是 /enroll。這個 API 用來讓學生選課。student_id 和 course_id:從請求中提取學生和課程的 ID。INSERT INTO enrollments (student_id, course_id):將選課資訊插入到 enrollments 資料表中。前端是一個簡單的 HTML 頁面,通過 JavaScript 與 Flask API 互動。
<form id="enrollForm">
學生 ID: <input type="text" id="student_id"><br><br>
課程 ID: <input type="text" id="course_id"><br><br>
<button type="submit">選課</button>
</form>
document.getElementById('enrollForm').onsubmit = function(event) {
event.preventDefault();
const studentId = document.getElementById('student_id').value;
const courseId = document.getElementById('course_id').value;
fetch('/enroll', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ student_id: studentId, course_id: courseId })
})
.then(response => response.text())
.then(data => alert(data));
};
onsubmit:攔截表單的提交動作。fetch('/enroll', ...):向 /enroll API 發送 POST 請求,將選課資訊發送到伺服器。JSON.stringify():將 JavaScript 對象轉換為 JSON 格式,發送至後端。fetch('/courses')
.then(response => response.json())
.then(courses => {
const coursesList = document.getElementById('coursesList');
courses.forEach(course => {
const li = document.createElement('li');
li.textContent = `課程 ID: ${course[0]}, 課程名稱: ${course[1]}`;
coursesList.appendChild(li);
});
});
fetch('/courses'):向 /courses API 發送 GET 請求,取得所有課程。前端的 HTML 和 JavaScript 被 Nginx 提供服務。
apiVersion: apps/v1
kind: Deployment
metadata:
name: frontend
spec:
selector:
matchLabels:
app: frontend
template:
metadata:
labels:
app: frontend
spec:
containers:
- name: nginx
image: nginx:latest
volumeMounts:
- name: html
mountPath: /usr/share/nginx/html
volumes:
- name: html
configMap:
name: frontend-html
---
apiVersion: v1
kind: ConfigMap
metadata:
name: frontend-html
data:
index.html: |
<!-- HTML 文件內容 -->
---
apiVersion: v1
kind: Service
metadata:
name: frontend
spec:
ports:
- port: 80
selector:
app: frontend
nginx:用來提供靜態 HTML 文件服務。ConfigMap:將 index.html 內容儲存在 ConfigMap 中,並掛載到 Nginx 容器的 /usr/share/nginx/html 目錄下。Service:對外暴露 Nginx 服務,使用默認的 HTTP 端口 80。這個系統是一個簡單的選課系統,前端通過 Nginx 提供靜態頁面服務,後端 Flask API 用來處理資料庫操作,MySQL 資料庫存放課程和選課信息。每個部分都通過 Kubernetes 來管理和調度,使應用能夠在容器化環境中運行。